package cn.shop.gameapi.consumer;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.shop.gameapi.model.GameNpc;
import cn.shop.gameapi.model.GatewaySecret;
import cn.shop.gameapi.model.MerchantGamePartition;
import cn.shop.gameapi.model.MerchantUser;
import cn.shop.msgs.PartitionMsg;
import cn.shop.utils.ApiCode;
import cn.shop.utils.ApiResult;
import cn.shop.utils.Putif;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQReplyListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

import static cn.shop.gameapi.model.SqlContent.SELECT_MERCHANT_BY_ID;
import static cn.shop.gameapi.model.SqlContent.SELECT_NPC;
import static cn.shop.gameapi.model.SqlContent.SELECT_PARTITION;
import static cn.shop.gameapi.model.SqlContent.SELECT_SECRET_IP_UID;

/**
 * @author : 李一涵
 * @date : Created in 2021-12-17 14:19
 * @description :
 */
@RocketMQMessageListener(topic = PartitionMsg.TOPIC, consumerGroup = "partition-consumer", selectorExpression = PartitionMsg.TAG)
public class PartitionConsumer implements RocketMQReplyListener<PartitionMsg, ApiResult<Map<String, Object>>> {

    private static final Logger LOG = LoggerFactory.getLogger(PartitionConsumer.class);

    @Resource
    private ObjectMapper objectMapper;
    @Resource
    private JdbcTemplate jdbcTemplate;

    @Override
    public ApiResult<Map<String, Object>> onMessage(PartitionMsg msg) {
        LOG.info("{}", msg);
        if (msg == null) {
            return ApiResult.fail("服务器错误");
        }
        MerchantGamePartition partition = null;
        try {
            partition = jdbcTemplate.queryForObject(SELECT_PARTITION, new BeanPropertyRowMapper<>(MerchantGamePartition.class), msg.getIds().get(0));
        } catch (Exception ignored) {}
        LOG.info("{}", partition);
        if (partition == null) {
            return ApiResult.fail("分区不存在");
        }
        List<GameNpc> npcs = jdbcTemplate.query(SELECT_NPC, new BeanPropertyRowMapper<>(GameNpc.class), partition.getId());
        partition.setNpcs(npcs);
        MerchantUser user = null;
        try {
            user = jdbcTemplate.queryForObject(SELECT_MERCHANT_BY_ID, new BeanPropertyRowMapper<>(MerchantUser.class), msg.getUid());
        } catch (Exception ignored) {}
        if (user == null) {
            return ApiResult.fail("商户不存在");
        }
        try {
            return sendPartition(partition, msg.getUid(), partition.getAlias());
        } catch (Exception e) {
            LOG.warn("同步分区失败", e);
            return ApiResult.fail(ApiCode.SUCCESS_SEND_FAIL, "分区创建成功，但NPC脚本创建失败（由于与IP为" + partition.getIp() + "端口号为" + partition.getPort() + "的网关无法进行链接，请检查网关是否运行或者IP和端口是否正确）");
        }
    }

    private ApiResult<Map<String, Object>> sendPartition(MerchantGamePartition partition, long uid, String alias) throws Exception {
        GatewaySecret secret = null;
        try {
            secret = jdbcTemplate.queryForObject(SELECT_SECRET_IP_UID, new BeanPropertyRowMapper<>(GatewaySecret.class), partition.getIp(), uid);
        } catch (EmptyResultDataAccessException ignored) {}
        Map<String, Object> body = Putif.start()
                .anyway("id", partition.getId())
                .anyway("templateId", partition.getTemplateId())
                .anyway("name", partition.getName())
                .anyway("serverFolder", partition.getServerFolder())
                .anyway("npcs", partition.getNpcs())
                .anyway("createScript", partition.getCreateScript())
                .anyway("alias", alias)
                .get();
        LOG.info("{} {} {}", partition.getIp(), partition.getPort(), partition);
        String url = "http://" + partition.getIp() + ":" + partition.getPort() + "/gateway/api/partition/add";
        String json = HttpUtil.createPost(url)
                .header("secret", secret != null ? secret.getSecret() : "")
                .body(objectMapper.writeValueAsString(body))
                .execute()
                .body();
        LOG.info("同步分区返回结果:" + json);
        if (StrUtil.isBlank(json)) {
            return ApiResult.fail("秘钥无效");
        }
        return objectMapper.readValue(json, new TypeReference<ApiResult<Map<String, Object>>>() {});
    }
}
